$.jCarouselLite = {
    version: '1.2.0-alpha'
};

/**
 * 请勿替换此插件，因为修改了源代码，使其符合学科网首页的要求。
 * 1.添加了省级联动选择器的选项，使点击省份的时候可以联动下面的图片一起滚动
 */

$.fn.jCarouselLite = function(options) {

    options = $.extend({}, $.fn.jCarouselLite.options, options || {});


    return this.each(function() { // Returns the element collection. Chainable.

        var running,
            animCss, sizeCss,
            div = $(this),
            ul, initialLi, li,
            liSize, ulSize, divSize,
            numVisible, initialItemLength, itemLength, calculatedTo, autoTimeout;

        initVariables(); // Set the above variables after initial calculations
        initStyles(); // Set the appropriate styles for the carousel div, ul and li
        initSizes(); // Set appropriate sizes for the carousel div, ul and li
        attachEventHandlers(); // Attach event handlers for carousel to respond

        /**
         * Navigates the carousel to an element at "to" index
         * In the process, it adjusts the carousel based on whether it circular or not, hightlights the go buttons,
         * disables/enables the next/prev buttons and so on
         * @param to
         * @returns {boolean}
         */
        function go(to) {
            if (!running) {
                clearTimeout(autoTimeout); // Prevents multiple clicks while auto-scrolling - edge case
                calculatedTo = to;

                if (options.beforeStart) { // Call the beforeStart() callback
                    options.beforeStart.call(this, visibleItems());
                }

                if (options.circular) { // If circular, and "to" is going OOB, adjust it
                    adjustOobForCircular(to);
                } else { // If non-circular and "to" is going OOB, adjust it.
                    adjustOobForNonCircular(to);
                } // If neither overrides "calculatedTo", we are not in edge cases.

                animateToPosition({ // Animate carousel item to position based on calculated values.
                    start: function() {
                        running = true;
                    },
                    done: function() {
                        if (options.afterEnd) {
                            options.afterEnd.call(this, visibleItems());
                        }
                        if (options.auto && !paused) {
                            setupAutoScroll();
                        }
                        running = false;
                    }
                });

                highlightGoButtons(); // Highlight or Un-highlight the right external GO buttons

                if (!options.circular) { // Enabling / Disabling buttons is applicable in non-circular mode only.
                    disableOrEnableButtons();
                }

            }
            return false;
        }

        /**
         * Setup the initial set of variables based on the options set by the user.
         */
        function initVariables() {
            running = false;
            animCss = options.vertical ? "top" : "left";
            sizeCss = options.vertical ? "height" : "width";
            ul = div.find(">ul");
            initialLi = ul.find(">li");
            initialItemLength = initialLi.size();

            // To avoid a scenario where number of items is just 1 and visible is 3 for example.
            numVisible = initialItemLength < options.visible ? initialItemLength : options.visible;

            if (options.circular) {
                var $lastItemSet = initialLi.slice(initialItemLength - numVisible).clone();
                var $firstItemSet = initialLi.slice(0, numVisible).clone();

                ul.prepend($lastItemSet) // Prepend the lis with final items so that the user can click the back button to start with
                    .append($firstItemSet); // Append the lis with first items so that the user can click the next button even after reaching the end

                options.start += numVisible; // Since we have a few artificial lis in the front, we will have to move the pointer to point to the real first item
            }

            li = $("li", ul);
            itemLength = li.size();
            calculatedTo = options.start;
        }

        /**
         * Gives the carousel elements some default styles so that they align well into a carousel format.
         * This method will not give any themed styles, just the bare minimum necessary to make the carousel work
         */
        function initStyles() {
            div.css("visibility", "visible"); // If the div was set to hidden in CSS, make it visible now

            li.css({
                overflow: "hidden",
                "float": options.vertical ? "none" : "left" // Some minification tools fail if "" is not used
            });

            ul.css({
                margin: "0",
                padding: "0",
                position: "relative",
                "list-style": "none",
                "z-index": "1"
            });

            div.css({
                overflow: "hidden",
                position: "relative",
                "z-index": "2",
                left: "0px"
            });

            calculatedTo = options.start;

            // For a non-circular carousel, disable or enable the nav buttons
            if (!options.circular) {
                disableOrEnableButtons();
            }

            // Highlight the GO buttons immediately after carousel initialization
            highlightGoButtons();

        }

        /**
         * Sets the size of various carousel elements based on the given user inputs like width/height
         * of the carousel element.
         */
        function initSizes() {

            liSize = options.vertical ? // Full li size(incl margin)-Used for animation and to set ulSize
                li.outerHeight(true) :
                li.outerWidth(true);
            ulSize = liSize * itemLength; // size of full ul(total length, not just for the visible items)
            divSize = liSize * numVisible; // size of entire div(total length for just the visible items)

            // Generally, LI's dimensions should be specified explicitly in a style-sheet
            // But in the case of img (with width and height attr), we can derive LI's dimensions and set here
            // May be applicable for other types of LI children if their dimensions are explicitly specified
            // Individual LI dimensions
            li.css({
                width: li.width(),
                height: li.height()
            });

            // Size of the entire UL. Including hidden and visible elements
            // Will include LI's (width + padding + border + margin) * itemLength - Using outerwidth(true)
            ul.css(sizeCss, ulSize + "px")
                .css(animCss, -(calculatedTo * liSize));

            // Width of the DIV. Only the width of the visible elements
            // Will include LI's (width + padding + border + margin) * numVisible - Using outerwidth(true)
            div.css(sizeCss, divSize + "px");

        }

        /**
         * Attach event handlers to the carousel elements based on options
         */
        function attachEventHandlers() {
            if (options.btnPrev) {
                $(options.btnPrev).click(function() {
                    return go(calculatedTo - options.scroll);
                });
            }

            if (options.btnNext) {
                $(options.btnNext).click(function() {
                    //在这里添加往后翻页的事件
                    return go(calculatedTo + options.scroll);
                });
            }

            /**
             * 省级联动，学科网首页-->名校资源选项卡的省级联动
             * @param  {[type]} options.provinceMap [description]
             * @return {[type]}                     [description]
             * @author zuokangsheng
             */

            if (options.provinceMap) {
                $('.' + options.provinceMap.parentClass).click(function() {
                    //获取点击省份
                    var thisIndex = $(this).index();
                    var currentIndex = $('.' + options.provinceMap.parentClass + '.' + options.provinceMap.childClass).index();
                    return thisIndex !== currentIndex && go(calculatedTo + options.scroll - 1 + thisIndex - currentIndex);
                });
            }

            if (options.btnGo) {
                $.each(options.btnGo, function(i, val) {
                    $(val).click(function() {
                        return go(options.circular ? numVisible + i : i);
                    });
                });
            }

            if (options.mouseWheel && div.mousewheel) {
                div.mousewheel(function(e, d) {
                    return d > 0 ?
                        go(calculatedTo - options.scroll) :
                        go(calculatedTo + options.scroll);
                });
            }

            if (options.auto) {
                setupAutoScroll();
                if (options.onMouse) {
                    /*ul.bind("mouseover", function() {
                                    if(options.auto) {
                                        clearTimeout(autoTimeout);
                                    }
                                });
                                //mouseout
                                ul.bind("mouseout", function() {
                                    if(options.auto) {
                                        setupAutoScroll();
                                    }
                                });*/
                    paused = false;
                    ul.hover(function() {
                        if (options.auto && !paused) {
                            clearTimeout(autoTimeout);
                            paused = true;
                        }
                    }, function() {
                        if (options.auto && paused) {
                            setupAutoScroll();
                            paused = false;
                        }
                    });
                }

            }
        }

        function pause() {
            clearTimeout(autoTimeout);
            paused = true;
        }

        function play() {
            setupAutoScroll();
            paused = false;
        }

        /**
         * Sets up auto-scroll
         */
        function setupAutoScroll() {
            autoTimeout = setTimeout(function() {
                go(calculatedTo + options.scroll);
            }, options.auto);
        }

        /**
         * Returns a list of currently visible items in the carousel
         * @returns {*}
         */
        function visibleItems() {
            return li.slice(calculatedTo).slice(0, numVisible);
        }

        /**
         * For a circular carousel, we need to simulate the infinite mode.
         * This method adjusts the indexes of the carousel based on the current index for infinite mode.
         * @param to
         */
        function adjustOobForCircular(to) {
            var newPosition;

            // If first, then goto last
            if (to <= options.start - numVisible - 1) {
                newPosition = to + initialItemLength + options.scroll;
                ul.css(animCss, -(newPosition * liSize) + "px");
                calculatedTo = newPosition - options.scroll;

                //console.log("Before - Positioned at: " + newPosition + " and Moving to: " + calculatedTo);
            }

            // If last, then goto first
            else if (to >= itemLength - numVisible + 1) {
                newPosition = to - initialItemLength - options.scroll;
                ul.css(animCss, -(newPosition * liSize) + "px");
                calculatedTo = newPosition + options.scroll;

                //console.log("After - Positioned at: " + newPosition + " and Moving to: " + calculatedTo);
            }
        }

        /**
         * For a non-circular carousel, this method
         *  adjusts the calculatedTo to 0 if the carousel is at the first element.
         *  adjusts calculatedTo to a correct value when the carousel is going towards the last element.
         * The second point is a bit more complicated because, based on a combination of scroll, visible and
         * the total number of elements in the carousel the carousel will need to adjust its calculatedTo so that
         * the last element is made visible regardless of edge cases
         * @param to
         */
        function adjustOobForNonCircular(to) {
            // If user clicks "prev" and tries to go before the first element, reset it to first element.
            if (to < 0) {
                calculatedTo = 0;
            }
            // If "to" is greater than the max index that we can use to show another set of elements
            // it means that we will have to reset "to" to a smallest possible index that can show it
            else if (to > itemLength - numVisible) {
                calculatedTo = itemLength - numVisible;
            }

            console.log("Item Length: " + itemLength + "; " +
                "To: " + to + "; " +
                "CalculatedTo: " + calculatedTo + "; " +
                "Num Visible: " + numVisible);
        }

        /**
         * Enable or disable buttons in non-circular mode.
         */
        function disableOrEnableButtons() {
            $(options.btnPrev + "," + options.btnNext).removeClass(options.disabledClass);
            $((calculatedTo - options.scroll < 0 && options.btnPrev) ||
                (calculatedTo + options.scroll > itemLength - numVisible && options.btnNext) || []
            ).addClass(options.disabledClass);
        }

        /**
         * Highlight or un-highlight GO buttons based on the current item being displayed in the carousel.
         * In case of circular: true mode, we have some calculations to do, but in case of circular:false mode,
         * the calculatedTo variable is the index of the GO button to highlight
         */
        function highlightGoButtons() {
            if (options.btnGo) { // If GO buttons have been provided, only then get into highlighting mode

                var buttonIndex = calculatedTo;
                $(options.btnGo.join(", ")).removeClass(options.highlightClass);

                if (options.circular) { // If Circular, then we have some calculations to make, none otherwise
                    if (calculatedTo < numVisible) {
                        buttonIndex = calculatedTo + initialItemLength;
                    } else if (calculatedTo >= (initialItemLength + numVisible)) {
                        buttonIndex = calculatedTo - initialItemLength
                    }
                    buttonIndex -= numVisible;
                }

                $(options.btnGo[buttonIndex]).addClass(options.highlightClass);
            }
        }

        /**
         * Perform animation to move item from one position to another
         * @param animationOptions
         */
        function animateToPosition(animationOptions) {
            running = true;

            ul.animate(
                animCss == "left" ? {
                    left: -(calculatedTo * liSize)
                } : {
                    top: -(calculatedTo * liSize)
                },

                $.extend({
                    duration: options.speed,
                    easing: options.easing
                }, animationOptions)
            );
        }
    });
};

$.fn.jCarouselLite.options = {
    btnPrev: null, // CSS Selector for the previous button
    btnNext: null, // CSS Selector for the next button
    btnGo: null, // CSS Selector for the go button
    mouseWheel: false, // Set "true" if you want the carousel scrolled using mouse wheel
    auto: null, // Set to a numeric value (800) in millis. Time period between auto scrolls
    onMouse: true, //澧炲姞榧犳爣鎮仠鍔熻兘

    speed: 200, // Set to a numeric value in millis. Speed of scroll
    easing: null, // Set to easing (bounceout) to specify the animation easing

    vertical: false, // Set to "true" to make the carousel scroll vertically
    circular: true, // Set to "true" to make it an infinite carousel
    visible: 3, // Set to a numeric value to specify the number of visible elements at a time
    start: 0, // Set to a numeric value to specify which item to start from
    scroll: 1, // Set to a numeric value to specify how many items to scroll for one scroll event

    disabledClass: "disabled", // Class for navigation buttons in disabled mode. For non-circular mode
    highlightClass: "highlight", // Class for highlighting GO buttons when the corresponding item is displayed

    beforeStart: null, // Set to a function to receive a callback before every scroll start
    afterEnd: null, // Set to a function to receive a callback after every scroll end
    provinceMap: false //省级联动参数选项
};